package com.prs.crm.service.flow.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.prs.crm.context.Constrains;
import com.prs.crm.dao.flow.WorkFlowInstanceDao;
import com.prs.crm.domain.flow.WorkFlow;
import com.prs.crm.domain.flow.WorkFlowHandler;
import com.prs.crm.domain.flow.WorkFlowInstance;
import com.prs.crm.domain.flow.WorkFlowInstanceNode;
import com.prs.crm.domain.flow.WorkFlowNode;
import com.prs.crm.domain.flow.WorkFlowTransition;
import com.prs.crm.domain.flow.WorkFlowType;
import com.prs.crm.domain.hr.Person;
import com.prs.crm.domain.sys.Form;
import com.prs.crm.exception.InValidException;
import com.prs.crm.service.flow.WorkFlowInstanceService;
import com.prs.crm.service.flow.WorkFlowService;
import com.prs.crm.service.hr.PersonService;
import com.prs.crm.service.impl.BaseServiceImpl;
import com.prs.crm.vo.flow.FlowExecutor;
import com.prs.crm.vo.flow.FlowNode;
import com.prs.crm.vo.flow.FlowRelation;
import com.prs.crm.vo.flow.FlowView;
public class WorkFlowInstanceServiceImpl extends
	BaseServiceImpl<WorkFlowInstance,WorkFlowInstanceDao> implements WorkFlowInstanceService {
	
	private WorkFlowService workflowService;
	
	private PersonService personService;
	
	public void setWorkflowService(WorkFlowService workflowService) {
		this.workflowService = workflowService;
	}

	public WorkFlowService getWorkflowService() {
		return workflowService;
	}
	
	public void setPersonService(PersonService personService) {
		this.personService = personService;
	}

	public PersonService getPersonService() {
		return personService;
	}

	public WorkFlowInstance getFormFlowInstance(Form form,WorkFlow flow)
	{
		return this.getDao().findInstance(form,flow);
	}
	
	public void save(WorkFlowInstance instance,List<WorkFlowHandler> handlers)
	{
		try
		{
		
			if (handlers!=null)
			{
				verifyHandler(instance,handlers);
			}
			if (instance.getState()==null)
			{
				instance.setState(Constrains.WORKFLOWSTATE_ENABLE);
			}
			WorkFlowInstance forminstance = this.getFormFlowInstance(instance.getForm(),instance.getFlow());
			if (forminstance!=null )
			{
				if (instance.getId()==null || !forminstance.getId().equals(instance.getId()))
					throw new InValidException("表单已被同一流程关联");
			}
		
			super.save(instance);
	
			int i=0;
			if (instance.getNodes()==null || instance.getNodes().size()<1)
			{
				for (WorkFlowNode flownode : instance.getFlow().getNodes())
				{
					WorkFlowInstanceNode instanceNode = new WorkFlowInstanceNode();
					instanceNode.setFlownode(flownode);
					instanceNode.setInstance(instance);
					instanceNode.setProcessMode(Constrains.FLOWINSTANCEPROCESS_TYPE_DEFAULT);
					if (handlers!=null)
						instanceNode.setHandler(handlers.get(i++));
					instance.getNodes().add(instanceNode);
					this.getDao().saveNode(instanceNode);
				}
			}
			else if (handlers!=null)
			{
				for (WorkFlowInstanceNode node : instance.getNodes())
				{
					if (node.getHandler()!=null)
					{
						node.getHandler().copyFrom(handlers.get(i++));
					}
					else
					{
						node.setHandler(handlers.get(i++));
					}
					this.getDao().saveNode(node);
				}
			}
			super.save(instance);
		
		}
		catch (InValidException e)
		{
			throw e;
		}
		
	}
	
	public WorkFlowInstance findEnforeInstance(Form form)
	{
		return this.getDao().findEnforeInstance(form);
	}
	

	public Collection<WorkFlowInstance> findFormInstance(Form form, WorkFlowType type)
	{
		return this.getDao().findFormInstance(form,type,Constrains.WORKFLOWSTATE_ENABLE);
	}
	
	/**
	 * 验证选择是否有效,在选择节点审批人员时
	 * @param node
	 */
	private void verifyHandler(WorkFlowInstance instance,List<WorkFlowHandler> handlers)
	{
		if (instance.getNodes()!=null)
		{
			for (@SuppressWarnings("unused") WorkFlowInstanceNode node :instance.getNodes())
			{
				
			}
		}
		
		for (WorkFlowHandler handler : handlers)
		{
			if (handler.getRole()!=null
					&& handler.getDept()!=null)
			{
				Collection<Person> persons = this.getPersonService().getDeptRolePersons(
						handler.getDept(),handler.getRole());
				if (persons.size()<1)
				{
					throw new InValidException(handler.getDept().getName()+"不存在角色为"+handler.getRole().getName()+"的人员");
				}
			}
		}
	}
//	
//	public void save(WorkFlowInstance instance,Integer[] responsibleTypes)
//	{
//		if (instance.getState()==null)
//		{
//			instance.setState(Constrains.WORKFLOWSTATE_ENABLE);
//		}
//		WorkFlowInstance forminstance = this.getFormFlowInstance(instance.getForm());
//		if (forminstance!=null)
//		{
//			if (instance.getId()==null || !forminstance.getId().equals(instance.getId()))
//				throw new InValidException("\u8868\u5355\u5df2\u7ecf\u88ab\u5176\u4ed6\u6d41\u7a0b\u5173\u8054");
//		}
//		super.save(instance);
//		if (instance.getNodes()==null ||
//				instance.getNodes().size()<1)
//		{
//			int i=0;
//			for (WorkFlowNode flownode : instance.getFlow().getNodes())
//			{
//				WorkFlowInstanceNode instanceNode = new WorkFlowInstanceNode();
//				instanceNode.setFlownode(flownode);
//				instanceNode.setInstance(instance);
//				instanceNode.setProcessMode(Constrains.FLOWINSTANCEPROCESS_TYPE_DEFAULT);
//				if (responsibleTypes!=null)
//					instanceNode.setResponsibleType(responsibleTypes[i++]);
//				instance.getNodes().add(instanceNode);
//				this.getDao().saveNode(instanceNode);
//			}
//		}
//		else if (responsibleTypes!=null)
//		{
//			int i=0;
//			for (WorkFlowInstanceNode instanceNode: instance.getNodes())
//			{
//				if (instanceNode.getFlownode().getType()!=Constrains.WORKFLOW_STARTNODE
//						 && instanceNode.getFlownode().getType()!=Constrains.WORKFLOW_ENDNODE)
//				{
//					instanceNode.setResponsibleType(responsibleTypes[i++]);
//				}
//			}
//		}
//		super.save(instance);
//	}
	
	public int countFlowInstance(WorkFlow workflow)
	{
		return this.getDao().countFlowInstance(workflow);
	}
	
	public 	void executeEnable(WorkFlowInstance instance)
	{
		instance.setState(Constrains.WORKFLOWSTATE_ENABLE);
		super.save(instance);
	}
	
	public void executeDisable(WorkFlowInstance instance)
	{
		instance.setState(Constrains.WORKFLOWSTATE_DISABLE);
		super.save(instance);
	}
	
	public 	FlowView convert(WorkFlowInstance instance)
	{
		FlowView view = new FlowView();
		Map<Integer,FlowNode> nodes = new HashMap<Integer,FlowNode>();
		for (WorkFlowNode fnode : instance.getFlow().getNodes())
		{
			FlowNode node = new FlowNode();
			node.setId(fnode.getId());
			node.setName(fnode.getName());
			node.setxCoordinate(fnode.getExtra().getXcoordinate());
			node.setyCoordinate(fnode.getExtra().getYcoordinate());
			nodes.put(node.getId(), node);
		}
		view.setNodes(nodes.values());
		
		Collection<FlowRelation> relations = new ArrayList<FlowRelation>();
		for (WorkFlowTransition trans  : instance.getFlow().getTransitions())
		{
			FlowRelation relation = new FlowRelation(
					nodes.get(trans.getStartnode().getId()),
					nodes.get(trans.getEndnode().getId())
			);
			relations.add(relation);
		}
		view.setRelations(relations);
		return view;
	}
	
	public 	FlowExecutor convertHandler(WorkFlowInstanceNode node)
	{
		FlowExecutor executor = new FlowExecutor();
		if (node.getHandler()!=null)
		{
			if (node.getHandler().getDept()!=null)
			{
				executor.setDept(node.getHandler().getDept().getName());
			}
			if (node.getHandler().getRole()!=null)
			{
				executor.setRole(node.getHandler().getRole().getName());
			}
			if (node.getHandler().getPrincipal()!=null)
			{
				executor.setPrincipal(node.getHandler().getPrincipal().getResume().getName());
			}
			if (node.getHandler().getExecutors()!=null && node.getHandler().getExecutors().size()>0)
			{
				String str = null;
				for (Person person : node.getHandler().getExecutors())
				{
					str = (str==null)?person.getResume().getName():str+","+person.getResume().getName();
				}
			}
		}
		return executor;
	}

	@Override
	public WorkFlowInstance findByFormName(String name) {
		return this.getDao().findByFormName(name);
	}

	@Override
	public List<WorkFlowInstance> getAllWorkFlowInstance() {
		return this.getDao().getAllWorkFlowInstance();
	}
}
